﻿/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Kai Patrick
 * Datum: 01.04.2008
 * Zeit: 12:51
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */

using System;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using MSAst = Microsoft.Scripting.Ast;

namespace Gamadus.Engine.Compiler.Ast
{
	/// <summary>
	/// Description of Binary.
	/// </summary>
	public class Binary : Expression
	{
		private readonly Operator m_op;
        private readonly Expression m_left;
        private readonly Expression m_right;
        
		public Binary(Irony.Compiler.AstNode node) : base(node)
		{
			m_left = Expression.MakeExpression(node.ChildNodes[0]);
			m_right = Expression.MakeExpression(node.ChildNodes[2]);
			m_op = ParseOperator(node.ChildNodes[1]);
		}
		
		public Binary(Expression left, Expression right, Operator op)
		{
			m_left = left;
			m_right = right;
			m_op = op;
		}
		
		protected internal override Microsoft.Scripting.Ast.Expression Generate()
		{
			MSAst.Expression left = m_left.Generate();
            MSAst.Expression right = m_right.Generate();

            Operators op;
            switch (m_op)
            {
                // Binary
                case Operator.Add: op = Operators.Add; break;
                case Operator.Subtract: op = Operators.Subtract; break;
                case Operator.Multiply: op = Operators.Multiply; break;
                case Operator.Divide: op = Operators.Divide; break;

                // Comparisons
                case Operator.LessThan: op = Operators.LessThan; break;
                case Operator.LessThanOrEqual: op = Operators.LessThanOrEqual; break;
                case Operator.GreaterThan: op = Operators.GreaterThan; break;
                case Operator.GreaterThanOrEqual: op = Operators.GreaterThanOrEqual; break;
                case Operator.Equals: op = Operators.Equals; break;
                case Operator.NotEquals: op = Operators.NotEquals; break;

                default:
                    throw new System.InvalidOperationException();
            }
            return MSAst.Ast.Action.Operator(op, typeof(object), left, right);
		}
		
		Operator ParseOperator(Irony.Compiler.AstNode node)
		{
			switch((node as Irony.Compiler.Token).Text)
			{
				case "+":
					return Operator.Add;
				case "-":
					return Operator.Subtract;
				case "*":
					return Operator.Multiply;
				case "/":
					return Operator.Divide;
				case "div":
					return Operator.Div;
				case "mod":
					return Operator.Mod;
				case ">":
					return Operator.GreaterThan;
				case "<":
					return Operator.LessThan;
				case "==":
				case "=":
					return Operator.Equals;
				case ">=":
					return Operator.GreaterThanOrEqual;
				case "<=":
					return Operator.LessThanOrEqual;
				case "!=":
					return Operator.NotEquals;
				default:
					throw new ArgumentException("Invalid assignment symbol");
			}
		}
	}
}
